package com.hzw.saas.service.rss.parse;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class PDFParser {

    private final static String FIND_URL = "http://api.crossref.org/works/";

    private static PDFParser utils;

    public static PDFParser getInstance() {
        if (null == utils) {
            synchronized (PDFParser.class) {
                if (null == utils) {
                    utils = new PDFParser();
                }
            }
        }
        return utils;
    }



    private String findDesc(String content) {
        String tag = "Abstract";
        String str = StrUtil.EMPTY;
        for (int i = 0; i < content.length() - tag.length(); i++) {
            //判断当前字符串中的单个位置
            String substring = content.substring(i, i + tag.length());
            if (tag.equalsIgnoreCase(substring)) {
                //获取当前字符串位置
                str = content.substring(i + tag.length()).trim();
            }
        }

        if(StrUtil.isBlank(str)) {
            return str;
        }

        int lineFeedNum = findLineFeedNum(str);
        if (lineFeedNum <= 0) {
            return str;
        }
        StringBuilder desc = new StringBuilder();
        Double legal = null;
        for (int i = 0; i < lineFeedNum; i++) {
            int index = str.indexOf("\n");
            String s = str.substring(0, index);
            int length = s.length();
            if (i != 0 && legal != null && legal < length * 0.6) {
                break;
            }
            legal = length * 0.8;
            desc.append(s);
            str = str.substring(length + 1);
        }
        String trim = desc.toString().trim();
        String result = "";
        if (trim.startsWith(":")){
            String substring = trim.substring(1, trim.length());
            result = substring.trim();
        }else {
            result = trim;
        }
        int length = result.length();
        if (length>2000){
            String substring = result.substring(0, 1977);
            return substring+"...";
        }
        return result;
    }

    private Integer findLineFeedNum(String content) {
        if (StrUtil.isBlank(content)) {
            return 0;
        }
        String[] split = content.split("\n");
        return split.length - 1;
    }

    public String findDOI(String content) {
        int index = 0;
        int index4 = content.indexOf("doi");
        int index5 = content.indexOf("DOI");
        if (index4 < 0 && index5 <0) {
            return null;
        }
        if (index4 < 0){
            index = index5;
        }else {
            index = index4;
        }
        String substring = content.substring(index + 3);
        String doi;
        int index1;
        String substring1;
        if (substring.startsWith(":") || substring.startsWith(" ")) {
            String substring2 = substring.substring(1);
            String trim = substring2.trim();
            index1 = trim.indexOf(" ");
            substring1 = trim.substring(0, index1);
        } else {
            index1 = substring.indexOf(" ");
            substring1 = substring.substring(5, index1);
        }
        int index2 = substring1.indexOf("\n");
        doi = substring1;
        if (index2 > 0) {
            String substring2 = substring1.substring(0, index2);
            doi = substring2;
        }
        int index3 = substring1.indexOf("]");
        if (index3 > 0) {
            String substring2 = substring1.substring(0, index3);
            doi = substring2;
        }
        return doi;
    }

//    String findAuthors(String content) {
//        return null;
//    }
//
//    String findTitle(String content) {
//        return null;
//    }

    public Map<String, Object> getRss(File pdfFile) {
        Map<String, Object> result = new HashMap<>();
        try {
            result = getRssContent(parsingPdf(pdfFile));
            result.put("state", 0);
            return result;
        } catch (Exception e) {
           log.warn("未能提取到文献信息，请手动输入", e);
            result.put("state", -1);
            return result;
        }
    }

    public Map<String, Object> getRssContent(String content) {
        String desc = findDesc(content);
        String doi = findDOI(content);
        Map<String, Object> resultMap = handlerArticleInfo(doi);
        resultMap.put("description", desc);
        resultMap.put("doi", doi);
        return resultMap;
    }

    private Map<String, Object> handlerArticleInfo(String doi) {
        HashMap<String, Object> resultMap = new HashMap<>();
        String contentHTML = HttpUtil.get(FIND_URL.concat(doi));
        if (StrUtil.isBlank(contentHTML)) {
            return resultMap;
        }
        JSONObject jsonObject;
        try {
            jsonObject = JSONObject.fromObject(contentHTML);
        } catch (Exception e) {
            // ~ignore
            return resultMap;
        }
        JSONObject message = (JSONObject) jsonObject.get("message");

        if(message == null) {
            return resultMap;
        }

        // 设置标题
        setTitle(resultMap, message);
        // 设置作者
        setAuthor(resultMap, message);
        // 设置发布日期
        setPubDate(resultMap, message);
        // 设置期刊名称
        setJournalName(resultMap, message);

        return resultMap;

    }

    private void setJournalName(HashMap<String, Object> resultMap, JSONObject message) {
        JSONArray journalName = (JSONArray) message.get("short-container-title");
        resultMap.put("journalName", journalName.size() > 0 ? journalName.get(0).toString() : "");
    }

    private void setPubDate(HashMap<String, Object> resultMap, JSONObject message) {
        JSONObject created = (JSONObject) message.get("created");
        String pubDateStr = created.get("date-time").toString();
        resultMap.put("pubDate", DateUtil.parse(pubDateStr));
    }

    private void setTitle(HashMap<String, Object> resultMap, JSONObject message) {
        Object title = message.get("title");
        String trim = "";
        if (title.toString().length() > 3) {
            String substring = title.toString().substring(2, title.toString().length() - 2);
            trim = substring.trim();
        }
        resultMap.put("title", trim);
    }

    private void setAuthor(HashMap<String, Object> resultMap, JSONObject message) {
        JSONArray author = (JSONArray) message.get("author");
        List<String> authors = new ArrayList<>();
        if (!author.isEmpty()) {
            for (int i = 0; i < author.size(); i++) {
                JSONObject o = (JSONObject) author.get(i);
                Object given = o.get("given");
                Object family = o.get("family");
                authors.add(given.toString() + "." + family.toString());
            }
        }
        if (CollectionUtil.isNotEmpty(authors)) {
            resultMap.put("author", authors.stream().reduce("", (c, n) -> {
                if(StrUtil.isBlank(c)) {
                    return n;
                } else {
                    return c + "," + n;
                }
            }));
            resultMap.put("authors", authors);
        }
    }

    private String parsingPdf(File pdfFile) throws IOException {
        String content = "";
        PDDocument document = null;
        try {
            document = PDDocument.load(pdfFile);
            // 获取页码
            int pages = document.getNumberOfPages();
            // 读文本内容
            PDFTextStripper stripper = new PDFTextStripper();
            // 设置按顺序输出
            stripper.setSortByPosition(true);
            stripper.setStartPage(1);
            stripper.setEndPage(2);
            if (pages < 2) {
                stripper.setEndPage(pages);
            }
            content = stripper.getText(document);
        } finally {
            document.close();
        }
        return content;
    }

//    @SneakyThrows
//    public static void main(String[] args) {
//        File pdfFile = new File("/Users/syh/downloads/情景模拟教学法联合OSCE在ICU超声引导外周静脉穿刺培训实践.pdf");
//        System.out.println(PDFParser.getInstance().getRss(pdfFile));
//    }
}
